#include <vector>
#include <string>
#include <map>
#include <set>
#include <fstream>
#include <sstream>
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
using std::string;
using std::set;
using std::map;
using std::vector;
using std::ifstream;
using std::istringstream;

class TextQuery
{
public:
    TextQuery()
    {   _file.reserve(110); };

    void readFile(const string & filename);
    void query(const string & word);
private:
    void preprocessLine(string & line);//对一行进行处理
    void preprocessWord(string & word);

private:
    vector<string> _file;
    map<string, int> _dict;
    map<string, set<int>> _word2Line;
};

void TextQuery::readFile(const string & filename)
{
    ifstream ifs(filename);
    if(!ifs) {
        cout << "ifstream open file " << filename << " error" << endl;
        return;
    }

    string line;
    int cnt = 0;
    while(std::getline(ifs, line)){
        _file.push_back(line);//存在vector中的是原始行
        preprocessLine(line);

        istringstream iss(line);
        string word;
        while(iss >> word){
            ++_dict[word];//统计词频
            _word2Line[word].insert(cnt);//统计单词出现的行号
        }
        ++cnt;
    }
    ifs.close();
}

void TextQuery::preprocessLine(string & line)
{
    for(auto & ch : line) {
        if(!isalpha(ch)) {
            ch = ' ';
        } else if(isupper(ch)) {
            ch = tolower(ch);
        }
    }
}

void TextQuery::preprocessWord(string & word)
{
    for(auto & ch : word) {
        if(isupper(ch)) {
            ch = tolower(ch);
        }
    }
}
    

void TextQuery::query(const string & word)
{
    string tmp(word);
    preprocessWord(tmp);
    //查询完毕之后，要打印结果集
    cout << word << " occurs " << _dict[tmp] << " times." << endl;
    set<int> & setInts = _word2Line[tmp]; 
    for(auto & num : setInts) {
        cout << "(line " << num + 1 << ") " << _file[num] << endl;
    }
}

void test0()
{
    TextQuery tq;
    tq.readFile("china_daily.txt");

    string sought;
    cout << "pls input a word to search:";
    while(cin >> sought, !cin.eof()) {
        tq.query(sought);
        cout << "pls input a word to search:";
    }
}


int main()
{
    test0();
    return 0;
}

